/*** 
 * @_______________#########_______________________ 
 * @______________############_____________________ 
 * @______________#############____________________ 
 * @_____________##__###########___________________ 
 * @____________###__######_#####__________________ 
 * @____________###_#######___####_________________ 
 * @___________###__##########_####________________ 
 * @__________####__###########_####_______________ 
 * @________#####___###########__#####_____________ 
 * @_______######___###_########___#####___________ 
 * @_______#####___###___########___######_________ 
 * @______######___###__###########___######_______ 
 * @_____######___####_##############__######______ 
 * @____#######__#####################_#######_____ 
 * @____#######__##############################____ 
 * @___#######__######_#################_#######___ 
 * @___#######__######_######_#########___######___ 
 * @___#######____##__######___######_____######___ 
 * @___#######________######____#####_____#####____ 
 * @____######________#####_____#####_____####_____ 
 * @_____#####________####______#####_____###______ 
 * @______#####______;###________###______#________ 
 * @________##_______####________####______________ 
 * @
 * @Author: ipk518 121206530@qq.com
 * @Date: 2025-06-04 16:03:31
 * @LastEditors: ipk518 121206530@qq.com
 * @LastEditTime: 2025-09-04 15:53:28
 * @FilePath: /etws-sxk2307/src/gnss/nmea0183.cpp
 * @Description: 
 * @你把时间投在专业上，两三年，你就能在圈子里小有名气。四五年，你就能靠这个专业赚钱。过了10年以上，你就能成为这个领域的专家
 * @Copyright (c) 2025 by etws@quyujiang, All Rights Reserved. 
 */

#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <unordered_map>
#include <iomanip>
#include "gnss.h"

#define NMEA_DEBUG  0

nmea0183Protocol::nmea0183Protocol(){}

nmea0183Protocol::~nmea0183Protocol(){}

// 计算校验和
unsigned char nmea0183Protocol::calculateChecksum(const std::string& sentence) {
    unsigned char checksum = 0;
    for (size_t i = 1; i < sentence.size() && sentence[i] != '*'; ++i) {
        checksum ^= sentence[i];
    }
    return checksum;
}

// 分割字符串
std::vector<std::string> nmea0183Protocol::split(const std::string &s, char delimiter) {
    std::vector<std::string> tokens;
    std::istringstream ss(s);
    std::string token;
    while (std::getline(ss, token, delimiter)) {
        tokens.push_back(token);
    }
    return tokens;
}


// 解析GAGSV句子
bool nmea0183Protocol::parseGAGSV(const std::vector<std::string>& fields, gnss_data_struct *gnssData) {
    if (fields.size() < 4) {
        // qlog_n("GAGSV字段不足");
        return false;
    }
#if NMEA_DEBUG == 1
    std::cout << "== GAGSV信息 ==" << std::endl;
    std::cout << "总消息数: " << fields[1] << std::endl;
    std::cout << "当前消息号: " << fields[2] << std::endl;
    std::cout << "可见卫星总数: " << fields[3] << std::endl;
    // 解析卫星信息
    for (size_t i = 4; i < fields.size(); i += 4) {
        if (i + 3 < fields.size()) {
            std::cout << "卫星编号: " << fields[i] << std::endl;
            std::cout << "仰角: " << fields[i + 1] << std::endl;
            std::cout << "方位角: " << fields[i + 2] << std::endl;
            std::cout << "信噪比: " << fields[i + 3] << std::endl;
        }
    }
#endif // NMEA_DEBUG
    
    return true;
}

// 解析GLGSV句子
bool nmea0183Protocol::parseGLGSV(const std::vector<std::string>& fields, gnss_data_struct *gnssData) {
    if (fields.size() < 4) {
        // qlog_n("GLGSV字段不足");
        return false;
    }
#if NMEA_DEBUG == 1
    std::cout << "== GLGSV信息 ==" << std::endl;
    std::cout << "总消息数: " << fields[1] << std::endl;
    std::cout << "当前消息号: " << fields[2] << std::endl;
    std::cout << "可见卫星总数: " << fields[3] << std::endl;
    // 解析卫星信息
    for (size_t i = 4; i < fields.size(); i += 4) {
        if (i + 3 < fields.size()) {
            std::cout << "卫星编号: " << fields[i] << std::endl;
            std::cout << "仰角: " << fields[i + 1] << std::endl;
            std::cout << "方位角: " << fields[i + 2] << std::endl;
            std::cout << "信噪比: " << fields[i + 3] << std::endl;
        }
    }
#endif // NMEA_DEBUG
    return true;
}

// 解析GPGSV句子
// $GAGSV,2,2,05,25,01,105,,2*41..
bool nmea0183Protocol::parseGPGSV(const std::vector<std::string>& fields, gnss_data_struct *gnssData) {
    if (fields.size() < 4) {
        // qlog_n("GPGSV字段不足");
        return false;
    }
#if NMEA_DEBUG == 1
    std::cout << "== GPGSV信息 ==" << std::endl;
    std::cout << "总消息数: " << fields[1] << std::endl;
    std::cout << "当前消息号: " << fields[2] << std::endl;
    std::cout << "可见卫星总数: " << fields[3] << std::endl;
    // 解析卫星信息
    for (size_t i = 4; i < fields.size(); i += 4) {
        if (i + 3 < fields.size()) {
            std::cout << "卫星编号: " << fields[i] << std::endl;
            std::cout << "仰角: " << fields[i + 1] << std::endl;
            std::cout << "方位角: " << fields[i + 2] << std::endl;
            std::cout << "信噪比: " << fields[i + 3] << std::endl;
        }
    }
#endif // NMEA_DEBUG
    return true;
}

// 解析GPGLL句子
// $GNGLL,2812.92251,N,11252.44676,E,085831.00,A,A*76..
// $GNGLL：报文标识符。
// 2812.92251,N：纬度（28°12.92251'N）。
// 11252.44676,E：经度（112°52.44676'E）。
// 085831.00,A,A：UTC 时间（08:58:31.00）和状态（A 表示有效）。
// *76：校验和
bool nmea0183Protocol::parseGPGLL(const std::vector<std::string>& fields, gnss_data_struct *gnssData) {
    if (fields.size() < 6) {
        // qlog_n("GPGLL字段不足");
        return false;
    }
#if NMEA_DEBUG == 1
    std::cout << "== GPGLL信息 ==" << std::endl;
    std::cout << "纬度: " << fields[1] << " " << fields[2] << std::endl;
    std::cout << "经度: " << fields[3] << " " << fields[4] << std::endl;
    std::cout << "UTC时间: " << fields[5] << std::endl;
    std::cout << "状态: " << fields[6] << std::endl;
#endif // NMEA_DEBUG

    return true;
}

// 解析GBGSV句子
// $GBGSV,1,1,01,22,42,304,37,1*42..
// $GBGSV：报文标识符。
// 1：报文类型（1 表示 GLONASS）。
// 1：总共有 1 个卫星组。
// 01：卫星组编号。
// 22：该组中可见的 GLONASS 卫星数量。
// 42：该组中可见的 GLONASS 卫星的编号。
// 304：该卫星的轨道编号。
// 37：该卫星的轨道状态。
// 1：该卫星的健康状态（1 表示正常）。
// *42：校验和（用于验证数据完整性）。
bool nmea0183Protocol::parseGBGSV(const std::vector<std::string>& fields, gnss_data_struct *gnssData) {
    if (fields.size() < 4) {
        // qlog_n("GBGSV字段不足");
        return false;
    }
#if NMEA_DEBUG == 1
    std::cout << "== GBGSV信息 ==" << std::endl;
    std::cout << "总消息数: " << fields[1] << std::endl;
    std::cout << "当前消息号: " << fields[2] << std::endl;
    std::cout << "可见卫星总数: " << fields[3] << std::endl;
    // 解析卫星信息
    for (size_t i = 4; i < fields.size(); i += 4) {
        if (i + 3 < fields.size()) {
            std::cout << "卫星编号: " << fields[i] << std::endl;
            std::cout << "仰角: " << fields[i + 1] << std::endl;
            std::cout << "方位角: " << fields[i + 2] << std::endl;
            std::cout << "信噪比: " << fields[i + 3] << std::endl;
        }
    }
#endif // NMEA_DEBUG
    return true;
}

// 解析GGA句子
// $GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47
bool nmea0183Protocol::parseGGA(const std::vector<std::string>& fields, gnss_data_struct *gnssData) {
    if (fields.size() < 15) {
        // qlog_n("GGA字段不足");
        return false;
    }
#if NMEA_DEBUG == 1
    std::cout << "== GGA信息 ==" << std::endl;
    std::cout << "UTC时间: " << fields[1] << std::endl;
    std::cout << "纬度: " << fields[2] << " " << fields[3] << std::endl;
    std::cout << "经度: " << fields[4] << " " << fields[5] << std::endl;
    std::cout << "定位质量: " << fields[6] << std::endl;
    std::cout << "卫星数: " << fields[7] << std::endl;
    std::cout << "HDOP: " << fields[8] << std::endl;
    std::cout << "海拔: " << fields[9] << " " << fields[10] << std::endl;
#endif // NMEA_DEBUG
    if (!fields[9].empty()) (void)strncpy((char *)gnssData->gnss_data_output.altitude,fields[9].data(), sizeof(gnssData->gnss_data_output.altitude));
    return true;
}

// 解析RMC句子
// $GNRMC,101138.00,A,2812.92445182,N,11252.44857826,E,0.005,13.5,150425,3.9,W,A,C*6C
bool nmea0183Protocol::parseRMC(const std::vector<std::string>& fields, gnss_data_struct *gnssData) {
    if (fields.size() < 12) {
        // qlog_n("RMC字段不足");
        return false;
    }
#if NMEA_DEBUG == 1
    std::cout << "== RMC信息 ==" << std::endl;
    std::cout << "UTC时间: " << fields[1] << std::endl;
    std::cout << "状态: " << fields[2] << std::endl;
    std::cout << "纬度: " << fields[3] << " " << fields[4] << std::endl;
    std::cout << "经度: " << fields[5] << " " << fields[6] << std::endl;
    std::cout << "速度 (节): " << fields[7] << std::endl;
    std::cout << "方位角: " << fields[8] << std::endl;
    std::cout << "UTC日期: " << fields[9] << std::endl;
#endif // NMEA_DEBUG
    // 检查 fields 元素是否为空，避免空值赋值
    if (!fields[1].empty()) gnssData->gnrmc.utc_time = fields[1];
    gnssData->gnrmc.location_status = (fields[2] == "A") ? 'A' : 'V';
    if (!fields[3].empty()) gnssData->gnrmc.latitude = fields[3];
    gnssData->gnrmc.latitude_latitude = (fields[4] == "N") ? 'N' : 0;

    if (!fields[5].empty()) gnssData->gnrmc.longitude = fields[5];
    gnssData->gnrmc.longitude_latitude = (fields[6] == "E") ? 'E' : 0;
    if (!fields[7].empty()) gnssData->gnrmc.speed = fields[7];
    if (!fields[8].empty()) gnssData->gnrmc.azimuth = fields[8];
    if (!fields[9].empty()) gnssData->gnrmc.utc_data = fields[9];
    return true;
}

// 主要解析函数
// $GPGGA：GPS 定位信息。
// $GPGSV：GPS 可见卫星信息。
// $GPGLL：地理定位信息。
// $GBGSV：GLONASS 可见卫星信息。
// $GPRMC：推荐最小定位信息。
void nmea0183Protocol::parse(const std::string& sentence, gnss_data_struct *gnssData) {
    // 检查句子以 ' 开头
    if (sentence.empty() || sentence[0] != '$') {
        // qlog_n("GNSS 无效句子. 必须以'$'开头");
        return;
    }

    // 找到校验符位置
    size_t starPos = sentence.find('*');
    if (starPos == std::string::npos) {
        // qlog_n("GNSS没有找到校验符.");
        return;
    }

    // 计算校验和
    unsigned char checksum = calculateChecksum(sentence);
    // 提取校验码
    unsigned int sentChecksum;
    std::istringstream ss(sentence.substr(starPos + 1));
    ss >> std::hex >> sentChecksum;

    // 比较校验码
    if (checksum != sentChecksum) {
#if NMEA_DEBUG == 1
        qlog_n("GNSS校验失败. 计算校验码: %02X, 接收到校验码: %02X", checksum, sentChecksum);
#endif
        return;
    }

    // 获取不带$和校验码的内容
    std::string dataPart = sentence.substr(1, starPos - 1);
    auto fields = split(dataPart, ',');

    if (fields.empty()) return;

    std::string type = fields[0];

    // 根据类型解析
    if (type == "GPGGA" || type == "GNGGA") { 
        parseGGA(fields,gnssData);
    } else if (type == "GPGSV" || type == "GNGSV") {
        parseGPGSV(fields,gnssData);
    } else if (type == "GPGLL" || type == "GNGLL") {
        parseGPGLL(fields,gnssData);
    } else if (type == "GBGSV") {
        parseGBGSV(fields,gnssData);
    } else if (type == "GPRMC" || type == "GNRMC") {
        parseRMC(fields,gnssData);
    } else if (type == "GAGSV") { // 新增GAGSV解析
        parseGAGSV(fields,gnssData);
    } else if (type == "GLGSV") { // 新增GLGSV解析
        parseGLGSV(fields,gnssData);
    } else {
        // qlog_e("GNSS未支持的句子类型: %s.", type.c_str());
    }
}


// int test() {
//     nmea0183Protocol parser;
//     gnss_data_struct st;
//     // 示例多条NMEA句子
//     std::vector<std::string> sentences = {
//         "$GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47",
//         "$GPRMC,235945.00,A,3751.65,S,14507.36,E,0.13,309.62,200520,,,A*77"
//     };

//     for (const auto& s : sentences) {
//         std::cout << "解析句子: " << s << std::endl;
//         parser.parse(s,&st);
//         std::cout << std::endl;
//     }

//     return 0;
// }


